package org.zn.note.jdk;

import java.util.concurrent.locks.*;

/**
 * AQS {@link AbstractQueuedSynchronizer} 抽象队列式同步器，(java.util.concurrent.locks 1.5 引入)
 * java 中除了synchronized外的锁机制。
 * CLH队列，是一种虚拟双向队列，没有队列实例，仅有节点间关系。（CLH是三个作者名字头字母）
 * 多线程获取共享资源：
 * 1、如果共享资源为空闲，则当前获取这个资源的线程被设置为“工作线程”(获取到锁了)，并发资源标记为“锁定”。
 * 2、如果共享资源为锁定，则需要阻塞等待、唤醒线程的机制，AQS用CLH队列实现的。将等待获取资源的线程封装为CLH队列节点。
 * <p>
 * AQS原理：
 * AQS就是基于CLH队列，用volatile修饰共享变量state(空闲？锁定？)，
 * 线程通过CAS去改变状态符，成功则获取锁成功，失败则进入等待队列，等待被唤醒。
 * <p>
 * 关于 {@link AbstractQueuedSynchronizer}
 * 1、父类 {@link AbstractOwnableSynchronizer}
 * 仅维护了当前工作线程：private transient Thread exclusiveOwnerThread; // 排他模式下的当前“工作线程”(获取到资源的线程)，有set、get方法
 * 2、静态内部类：Node （CLH 队列节点 Node）
 * ① 模式：SHARED 共享、EXCLUSIVE 排他
 * ② 状态：volatile int waitStatus;  SIGNAL、CANCELLED、CONDITION、PROPAGATE
 * ③ 前后节点：volatile Node prev, next; （实现CLH队列：虚拟双向队列）
 * ④ 这个节点封装的线程：volatile Thread thread;  创建Node时构造函数传入的，一个Node对应一个Thread
 * 3、一个Synchronizer维护一个state
 * private volatile int state;
 * getState、setState、compareAndSetState
 * <p>
 * Java锁相关的接口
 * {@link Lock} void lock(); // 阻塞直到获取到锁
 * {@link ReadWriteLock}
 * {@link Condition}
 * <p>
 * 关于 {@link ReentrantLock}
 * 实现了 Lock 接口。
 * 内部实现：
 * abstract static class Sync extends AbstractQueuedSynchronizer
 * 一、两个构造函数：
 * {@link ReentrantLock#ReentrantLock()} 默认非公平锁
 * {@link ReentrantLock#ReentrantLock(boolean)} true-公平锁  false-非公平锁
 */
public class JavaAQS {

    public static void main(String[] args) {
        try {
            new ReentrantLockTest().testLock();
        } catch (Exception e) {
            System.out.println("执行异常");
            e.printStackTrace();
        }
    }

    /**
     * ReentrantLock 标准用法
     */
    private static class ReentrantLockTest {
        private final ReentrantLock lock = new ReentrantLock();

        void testLock() throws Exception {
            lock.lock(); // 阻塞，直到获取到锁
            System.out.println("获取到锁");
            try {
                throw new Exception("业务处理异常");
            } finally {
                System.out.println("释放锁");
                lock.unlock(); // 必须要能保证释放锁
            }
        }
    }
}
